package com.hd.sup.modules.file.controller;

import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Maps;
import com.hd.common.constant.BizConstant;
import com.hd.common.page.BaseController;
import com.hd.common.reqres.response.Result;
import com.hd.common.utils.FileUploadUtils;
import com.hd.common.utils.GenUtil;
import com.hd.sup.modules.file.enums.UploadPathEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.utils.DateUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Map;

/**
 * @author chentl
 * @version V1.0
 * @Project 交通运输第三方监测平台
 * @Title FileController.java
 * @Description 文件上传
 * @Package com.hd.sup.modules.file.controller
 * @date 2021/1/14 6:00 下午
 * @Copyright: 深圳市宏电技术股份有限公司 All rights reserved.
 */
@Slf4j
@RestController
@RequestMapping("/file")
public class FileController extends BaseController {

    public static final String MB = "MB";
    public static final String FILE_SEPARATOR = "/";

    @Value("${spring.servlet.multipart.max-file-size}")
    private String maxFileSize;

    @Value("${file.http-path}")
    private String httpPath;

    /**
     * @return com.ops.common.quary.Result<?>
     * @Description 文件批量上传
     * @Name fileUpLoad
     * @Create 15:35 2020/12/6 0006
     * @Param [file, type,resType]
     **/
    @PostMapping("/upload")
    public Result<?> fileUpLoad(@RequestParam(value = "file") MultipartFile file, String type, String resType) {
        // valid 1 文件不为空
        if (file.isEmpty()) return Result.error("没有可上传的文件数据");
        // valid 2 文件保存类型不为空
        if (StringUtils.isBlank(type)) return Result.error("上传的文件保存类型为空");
        // valid 3 保存类型不匹配
        if (UploadPathEnum.get(type) == null) return Result.error("上保存类型不匹配，当前 type 支持的值: file、image、doc");
        // valid 4 文件大小溢出
        if (file.getSize() > Integer.parseInt(maxFileSize.split(MB)[0]) * 1024 * 1024)
            return Result.error("超过文件大小限制，最大限制为:" + maxFileSize);
        // valid 5 文件名不为空
        if (StringUtils.isBlank(file.getOriginalFilename())) return Result.error("上传的文件名不能为空");

        Date now = new Date();
        String originalFilename = file.getOriginalFilename();
        String path = type + FILE_SEPARATOR + DateUtils.formatDate(now, BizConstant.Common.DATE_FORMAT_DAY.key());

        //返回值
        Map<String, String> resultMap = Maps.newHashMap();
        try {
            InputStream stream = file.getInputStream();

            String extendName = originalFilename.substring(originalFilename.lastIndexOf(BizConstant.Common.POINT.key()));
            String uuidName = GenUtil.newId() + extendName;

            //ftp 上传
            FileUploadUtils.uploadFile(path, uuidName, stream);
            String httpUrl = httpPath + path + FILE_SEPARATOR + uuidName;

            if (StrUtil.isEmpty(httpUrl)) return Result.error("文件上传失败或已存在");
            resultMap.put(BizConstant.Columns.FILE_NAME.key(), originalFilename);
            resultMap.put(BizConstant.Columns.URL.key(), httpUrl);
            //关闭流
            stream.close();

            //需要base64 则直接返回
//            if (BizConstant.Common.BASE64.key().equalsIgnoreCase(resType)) {
//                String path = System.getProperty("user.dir") + File.separator + "upload-file" + File.separator + filePath + File.separator + uuidName;
//                File currentFile = new File(path);
//                if (!currentFile.exists() || !currentFile.isFile()) {
//                    return Result.error("文件不存在");
//                }
//                String base64str = "data:image/" + extendName + ";base64," + new String(Base64.getEncoder().encode(Files.readAllBytes(currentFile.toPath())));
//                resultMap.put(BizConstant.Common.BASE64.key(), base64str);
//            }


        } catch (Exception e) {
            log.error("文件上传时出现异常,{}", e.getMessage());
            return Result.error(e.getMessage());
        }


        return Result.success(resultMap);
    }

    /**
     * @return com.hd.sup.core.reqres.response.Result<?>
     * @author chentl
     * @description *
     * @date 2021/1/14 5:49 下午
     * @params [type, path, fileName, resType, response]
     */
    @GetMapping("/{type}/{path}/{fileName}")
    public Result<?> download(@PathVariable("type") String type,
                              @PathVariable("path") String path,
                              @PathVariable("fileName") String fileName,
                              String resType,
                              HttpServletResponse response) {
        if (StrUtil.isBlank(path)) {
            Result.error("文件相对路径不能为空");
            log.error("文件相对路径不能为空");
        }
        if (StrUtil.isBlank(fileName)) {
            log.error("文件相对路径不能为空");
            Result.error("文件相对路径不能为空");
        }

        OutputStream outputStream;
        FileInputStream fileInputStream;
        try {
            outputStream = response.getOutputStream();
            response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, StandardCharsets.UTF_8.toString()));
            response.setContentType("application/octet-stream; charset=utf-8");
            File file = new File(new File(new File(new File(System.getProperty("user.dir"), "upload-file").toString(), type).toString(), path).toString(), fileName);
            if (!(file.exists() && file.isFile())) outputStream.close();
            fileInputStream = new FileInputStream(file.toString());
            byte[] b = new byte[1024];
            int j;
            while ((j = fileInputStream.read(b)) > 0) {
                outputStream.write(b, 0, j);
            }
            fileInputStream.close();
            outputStream.flush();
            outputStream.close();
        } catch (IOException e) {
            log.error(e.getMessage());
        }
        return null;
    }

}
